package cn.codehaus.core.common.dao.impl;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.apache.commons.lang.xwork.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import cn.codehaus.core.common.dao.BaseHibernateDao;

@SuppressWarnings("unchecked")
public abstract class BaseHibernateDaoImpl<T> extends HibernateDaoSupport
		implements BaseHibernateDao 
	{
	Logger logger = Logger.getLogger("BaseHibernateDao-"
			+ typeClass().toString());

	boolean DESC = false;
	String orderPropertyName = "";

	public boolean delete(Object domain) {
		try {
			getHibernateTemplate().delete(domain);
			return true;
		} catch (Exception e) {
			logger.error(e);
			return false;
		}
	}

	public boolean delete(List domainList) {
		try {
			getHibernateTemplate().deleteAll(domainList);
			return true;
		} catch (Exception e) {
			logger.error(e);
			return false;
		}
	}

	public T save(Object domain) {
		try {
			getHibernateTemplate().save(domain);
			return (T) domain;
		} catch (Exception e) {
			logger.error(e);
			return null;
		}
	}

	public T saveOrUpdate(Object domain) {
		try {
			getHibernateTemplate().saveOrUpdate(domain);
			return (T) domain;
		} catch (Exception e) {
			logger.error(e);
			return null;
		}
	}

	public T update(Object domain) {
		try {
			getHibernateTemplate().update(domain);
			return (T) domain;
		} catch (Exception e) {
			logger.error(e);
			return null;
		}
	}

	public List<T> findByExample(Object value) {
		return getHibernateTemplate().findByExample(value);
	}

	public List<T> findByExample(String entityName, Object value) {
		return getHibernateTemplate().findByExample(entityName, value);
	}

	public List<T> findAll() {
		String queryString = "from " + getTableName();
		queryString = addOrderBy(queryString);
		return getHibernateTemplate().find(queryString);
	}

	public List<T> findAll(int firstResult, int size) {
		DetachedCriteria date = DetachedCriteria.forClass(typeClass());
		return getHibernateTemplate().findByCriteria(date, firstResult, size);
	}

	public T findById(Integer id) {
		return (T) getHibernateTemplate().get(typeClass(), id);
	}

	public List<T> findByProperty(String propertyName, Object value) {
		String queryString = "from " + getTableName()
				+ " as model where model." + propertyName + "= ? ";
		queryString = addOrderBy(queryString);
		return getHibernateTemplate().find(queryString, value);
	}

	public List<T> findIn(String propertyName, Object[] value) {
		DetachedCriteria date = DetachedCriteria.forClass(typeClass());
		date.add(Restrictions.in(propertyName, value));
		return getHibernateTemplate().findByCriteria(date);
	}

	public int getCount() {
		String queryString = "select count(*) from " + getTableName();
		List result = getHibernateTemplate().find(queryString);
		return ((Long) result.get(0)).intValue();
	}

	public int getCount(String propertyName, Object value) {
		String queryString = "select count(*) from " + getTableName()
				+ " as model where model." + propertyName + "= ? ";
		List result = getHibernateTemplate().find(queryString, value);
		return ((Long) result.get(0)).intValue();
	}

	public int getCount(String[] propertyNames, Object[] values) {
		String queryString = "select count(*) from " + getTableName()
				+ " as model where ";
		for (String propertyName : propertyNames) {
			queryString += " model." + propertyName + "=? and";
		}
		queryString = StringUtils.removeEnd(queryString, "and");
		List result = getHibernateTemplate().find(queryString, values);
		return ((Long) result.get(0)).intValue();
	}

	public List<T> findByProperty(String[] propertyNames, Object[] values) {
		String queryString = "from " + getTableName() + " as model where";
		for (String propertyName : propertyNames) {
			queryString += " model." + propertyName + "=? and";
		}
		queryString = StringUtils.removeEnd(queryString, "and");
		queryString = addOrderBy(queryString);
		return getHibernateTemplate().find(queryString, values);
	}

	public List<T> findByProperty(String propertyName, Object value,
			int firstResult, int size) {
		DetachedCriteria date = DetachedCriteria.forClass(typeClass());
		date.add(Restrictions.eq(propertyName, value));
		date = addOrderBy(date);
		return getHibernateTemplate().findByCriteria(date, firstResult, size);
	}

	public List fuzzyFindByProperty(String propertyName, Object value) {
		String queryString = " from " + getTableName()
				+ " as model where LOWER(model." + propertyName + ") like ?";
		String lowerValue = "%" + String.valueOf(value).toLowerCase() + "%";
		queryString = addOrderBy(queryString);
		return getHibernateTemplate().find(queryString, lowerValue);
	}

	// 取得泛型类型
	@SuppressWarnings("unchecked")
	protected Class<T> typeClass() {
		return (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}

	// 取得泛型tableName
	private String getTableName() {
		return typeClass().getSimpleName();
	}

	private String addOrderBy(String queryString) {
		if (!orderPropertyName.equals("")) {
			queryString += " order by model." + orderPropertyName;
			if (isDESC()) {
				queryString += " DESC";
			}
		}
		return queryString;
	}

	private DetachedCriteria addOrderBy(DetachedCriteria date) {
		if (!orderPropertyName.equals("")) {
			if (isDESC()) {
				date.addOrder(Order.desc(orderPropertyName));
			}
		}
		return date;
	}

	public String getOrderPropertyName() {
		return orderPropertyName;
	}

	public void setOrderPropertyName(String orderPropertyName) {
		this.orderPropertyName = orderPropertyName;
	}

	public boolean isDESC() {
		return DESC;
	}

	public void setDESC(boolean DESC) {
		this.DESC = DESC;
	}

}